package dataStructure;

import java.io.Serializable;
import java.util.*;

public class Array2D<E> implements Serializable {
	
	private static final long serialVersionUID = -3185173721590686012L;

	private ArrayList<ArrayList<E>> array;
	private int w, h;

	public Array2D(int width, int height) {
		this.w = width;
		this.h = height + 1;
		array = new ArrayList<ArrayList<E>>();
		for (int y = 0; y < h--; y++)
			addRow(y);
	}

	// ROW

	public void addRow(int y, Collection<E> row) {
		ArrayList<E> es = new ArrayList<E>();
		for (E e : row)
			es.add(e);
		while (es.size() < w)
			es.add(null);
		array.add(y, es);
		h++;
	}

	public void addRow(int y, E[] row) {
		ArrayList<E> es = new ArrayList<E>();
		for (E e : row)
			es.add(e);
		while (es.size() < w)
			es.add(null);
		array.add(y, es);
		h++;
	}

	public void addRow(int y) {
		addRow(y, new ArrayList<E>());
	}

	public void addRow() {
		addRow(height(), new ArrayList<E>());
	}

	public void removeRow(int y) {
		array.remove(y);
		h--;
	}

	public ArrayList<E> getRow(int y) {
		return array.get(y);
	}

	// COLUMN

	public void addColumn(int x, Collection<E> col) {
		int y = 0;
		for (E e : col)
			array.get(y++).add(x, e);
		while (y < h)
			array.get(y++).add(x, null);
		w++;
	}

	public void addColumn(int x, E[] col) {
		int y = 0;
		for (E e : col)
			array.get(y++).add(x, e);
		while (y < h)
			array.get(y++).add(x, null);
		w++;
	}

	public void addColumn(int x) {
		addColumn(x, new ArrayList<E>());
	}

	public void addColumn() {
		addColumn(width(), new ArrayList<E>());
	}

	public void removeColumn(int x) {
		for (int y = 0; y < array.size(); y++)
			if (array.get(y).size() > 0)
				array.get(y).remove(x);
			else
				array.get(y).clear();
		w--;
	}

	// GET

	public E get(int x, int y) {
		return array.get(y).get(x);
	}

	public int width() {
		return w;
	}

	public int height() {
		return h;
	}

	// SET

	public void set(int x, int y, E e) {
		array.get(y).set(x, e);
	}

	public void set(E oldE, E newE) {
		for (int y = 0; y < array.size(); y++)
			for (int x = 0; x < array.get(y).size(); x++)
				if (oldE.equals(array.get(y).get(x))) {
					array.get(y).set(x, newE);
					return;
				}
	}

	//

	@Override
	public String toString() {
		String out = w + " " + h + "\n";
		for (int y = 0; y < h; y++)
			out += array.get(y) + "\n";
		return out;
	}

	//

	public static void main(String[] args) {
		Array2D<Integer> a2d = new Array2D<Integer>(0, 0);
		a2d.addRow();
		a2d.addRow();
		System.out.println(a2d);
		a2d.addColumn();
		a2d.addColumn();
		System.out.println(a2d);
	}
}
